package com.sunyard.manage.controller;

import com.sunyard.constant.ErrMessageConst;
import com.sunyard.dal.bo.*;
import com.sunyard.dal.bo.device.lock.LogBO;
import com.sunyard.dal.bo.log.OperateHistoryBO;
import com.sunyard.dal.bo.log.SysLogBO;
import com.sunyard.dal.bo.warning.NotWorkingTimeBO;
import com.sunyard.dal.dto.NotWorkingTimeDTO;
import com.sunyard.dal.dto.OperateHistoryDTO;
import com.sunyard.dal.dto.SysLogQueryDTO;
import com.sunyard.dal.mapper.OperateHistoryMapper;
import com.sunyard.dal.mapper.OrganizationMapper;
import com.sunyard.dal.mapper.SystemLogMapper;
import com.sunyard.manage.service.OperatorLogService;
import com.sunyard.redisUtil.RedisUtils;
import com.sunyard.utils.DateUtil;
import com.sunyard.utils.ExcelOutput;
import com.sunyard.utils.Response.BaseResult;
import com.sunyard.utils.Response.GetResult;
import com.sunyard.utils.Response.HeaderResult;
import com.sunyard.utils.TokenUtil;
import com.sunyard.utils.manage.DataGrid;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;

import static java.util.stream.Collectors.toList;

/**
 * @author chengy.wei
 * @ClassNameOrganizationController
 * @Description 日志管理
 * @date 2012/7/06 15:21
 */

@Slf4j
@Api(tags = "OperatorLogController", description = "日志管理控制器")
@RestController
@RequestMapping(value = "/log")
public class OperatorLogController {

    @Autowired
    OperatorLogService operatorLogService;

    @Autowired
    private SystemLogMapper systemLogMapper;

    @Autowired
    private OperateHistoryMapper operateHistoryMapper;

    @Autowired
    private OrganizationMapper organizationMapper;

    @Autowired
    private RedisUtils redisUtils;

    /**
     * @Description: 系统分页查询
     * @Author: chengy.wei
     * @Date: 2012/7/06 15:21
     */
    @PostMapping(value = "/querySysLog")
    @ResponseBody
    @ApiOperation("系统日志查询")
    public BaseResult<DataGrid<SysLogQueryDTO>> querySysLog(@RequestBody PaginationBO<SysLogBO> logBOPaginationBO, HttpServletRequest request) {
        try {
            return operatorLogService.querySysLog(logBOPaginationBO, request);
        } catch (Exception e) {
            log.error(ErrMessageConst.SYSTEM_ERROR, e);
            return GetResult.getResultErr();
        }
    }

    /**
     * @Description: 操作日志查询
     * @Author: chengy.wei
     * @Date: 2012/7/06 15:21
     */
    @PostMapping(value = "/queryOperateLog")
    @ResponseBody
    @ApiOperation("操作日志查询")
    public BaseResult<DataGrid<OperateHistoryDTO>> queryHistory(@RequestBody PaginationBO<OperateHistoryBO> historyBOPaginationBO,
                                                                HttpServletRequest request) {
        try {
            return operatorLogService.queryHistory(historyBOPaginationBO, request);
        } catch (Exception e) {
            log.error(ErrMessageConst.SYSTEM_ERROR, e);
            return GetResult.getResultErr();
        }
    }

    /**
     * @Description: 操作日志查询
     * @Author: chengy.wei
     * @Date: 2012/7/06 15:21
     */
    @PostMapping(value = "/queryNotWorkingTimeLog")
    @ResponseBody
    @ApiOperation("非工作时间日志")
    public BaseResult<DataGrid<NotWorkingTimeDTO>> getNotWorkingTimeLog(@RequestBody PaginationBO<NotWorkingTimeBO> notWorkingTimeBOPaginationBO,
                                                                        HttpServletRequest request) {
        try {
            return operatorLogService.getNotWorkingTimeLog(notWorkingTimeBOPaginationBO, request);
        } catch (Exception e) {
            log.error(ErrMessageConst.SYSTEM_ERROR, e);
            return GetResult.getResultErr();
        }
    }

    /**
     * @Description: 非工作时间日志导出
     * @Author: tsz
     */
    @ApiOperation("非工作时间日志导出")
    @RequestMapping(value = "/notWorkingTimeLogExport")
    @ResponseBody
    public void notWorkingTimeLogExport(HttpServletResponse response, @RequestBody PaginationBO<NotWorkingTimeBO> notWorkingTimeBOPaginationBO, HttpServletRequest request) {
        try {
            String opId = TokenUtil.getOpId(request.getHeader("token"));
            String orgId = TokenUtil.getOrgId(request.getHeader("token"));
            String opName = TokenUtil.getOpName(request.getHeader("token"));
            operatorLogService.insert("非工作时间日志导出", "非工作时间日志导出", "1", opId, opName, orgId);
            NotWorkingTimeBO notWorkingTimeBO = notWorkingTimeBOPaginationBO.getParams();
            notWorkingTimeBO.setOrgId(orgId);
            // 执行查询
            //获取当前机构及下属机构id集合
            if (StringUtils.isBlank(notWorkingTimeBO.getOrgId())){
                notWorkingTimeBO.setOrgId(orgId);
            }
            List<String> orgIds = getListOrgIds(notWorkingTimeBO.getOrgId());
            orgIds.add(notWorkingTimeBO.getOrgId());
            notWorkingTimeBO.setOrgIds(orgIds);
            // 执行查询
            List<NotWorkingTimeDTO> list = operateHistoryMapper.getNotWorkingTimeLog(notWorkingTimeBO);
            if (list == null || list.isEmpty()) {
                throw new RuntimeException("无数据无需导出");
            }
            String title = "非工作时间日志导出" + Math.random() + ".xls";
            String[] headers = new String[]{"操作时间", "任务编号", "任务类型", "锁名称", "钥匙名称", "操作类型", "所属机构", "操作状态", "接收人1", "接收人2"};

            List<Object[]> dataList;
            dataList = list.stream().map(operateHistoryDTO -> {
                Object[] obj = new Object[headers.length];
                obj[0] = operateHistoryDTO.getOperateTime();
                obj[1] = operateHistoryDTO.getMissionId();
                obj[2] = operateHistoryDTO.getMissionType();
                obj[3] = operateHistoryDTO.getLockName();
                obj[4] = operateHistoryDTO.getKeyName();
                obj[5] = operateHistoryDTO.getOperateType();
                obj[6] = operateHistoryDTO.getOrgName();
                obj[7] = operateHistoryDTO.getOperateStatus();
                obj[8] = operateHistoryDTO.getOpName1();
                obj[9] = operateHistoryDTO.getOpName2();
                return obj;
            }).collect(toList());

            OutputStream out = null;
            // 防止中文乱码
            String headStr = "attachment; filename=\"" + new String(title.getBytes("gb2312"), "ISO8859-1") + "\"";
            response.setContentType("octets/stream");
            response.setContentType("APPLICATION/OCTET-STREAM");
            response.setHeader("Content-Disposition", headStr);
            out = response.getOutputStream();
            ExcelOutput ex = new ExcelOutput(title, headers, dataList);
            ex.export(out);
            log.info("非工作时间日志导出");
        } catch (Exception e) {
            log.error(ErrMessageConst.SYSTEM_ERROR, e);
            HeaderResult.setFailHeader(request, response, e.getMessage());
        }
    }


    /**
     * @Description: 系统日志导出
     * @Author: jiy.fang
     * @Date: 2019/7/23 21:10
     */
    @ApiOperation("系统日志导出")
    @RequestMapping(value = "/sysLogExport")
    @ResponseBody
    public void exportSysLogExport(HttpServletResponse response, @RequestBody PaginationBO<SysLogBO> sysLogQuery, HttpServletRequest request) {
        try {
            String opId = TokenUtil.getOpId(request.getHeader("token"));
            String orgId = TokenUtil.getOrgId(request.getHeader("token"));
            String opName = TokenUtil.getOpName(request.getHeader("token"));
            operatorLogService.insert("系统日志导出", "系统日志导出", "1", opId, opName, orgId);
            SysLogBO sysLogBO = sysLogQuery.getParams();
            sysLogBO.setOrgId(orgId);
            // 执行查询
            List<SysLogQueryDTO> sysLogQueryDTOS = systemLogMapper.getListSysLog(sysLogBO);
            if (sysLogQueryDTOS == null || sysLogQueryDTOS.isEmpty()) {
                throw new RuntimeException("无数据无需导出");
            }
            String title = "系统日志导出" + Math.random() + ".xls";
            String[] headers = new String[]{"操作时间","机构名称", "操作员", "操作名称", "操作描述"};

            List<Object[]> dataList;
            dataList = sysLogQueryDTOS.stream().map(sysLogQueryDTO -> {
                Object[] obj = new Object[headers.length];
                obj[0] = sysLogQueryDTO.getCreateDatetime();
                obj[1] = sysLogQueryDTO.getOrgName();
                obj[2] = sysLogQueryDTO.getOpName();
                obj[3] = sysLogQueryDTO.getLogName();
                obj[4] = sysLogQueryDTO.getOperationDesc();
                return obj;
            }).collect(toList());

            OutputStream out = null;
            // 防止中文乱码
            String headStr = "attachment; filename=\"" + new String(title.getBytes("gb2312"), "ISO8859-1") + "\"";
            response.setContentType("octets/stream");
            response.setContentType("APPLICATION/OCTET-STREAM");
            response.setHeader("Content-Disposition", headStr);
            out = response.getOutputStream();
            ExcelOutput ex = new ExcelOutput(title, headers, dataList);
            ex.export(out);
            log.info("系统日志导出");

        } catch (Exception e) {
            log.error(ErrMessageConst.SYSTEM_ERROR, e);
            HeaderResult.setFailHeader(request, response, e.getMessage());
        }
    }

    /**
     * @Description: 操作日志导出
     * @Author: jiy.fang
     * @Date: 2019/7/23 21:10
     */
    @ApiOperation("操作日志导出")
    @RequestMapping(value = "/operateLogExport")
    @ResponseBody
    public void exportOperateLogExport(HttpServletResponse response, @RequestBody PaginationBO<OperateHistoryBO> historyBOPaginationBO,
                                       HttpServletRequest request) {
        try {
            String opId = TokenUtil.getOpId(request.getHeader("token"));
            String orgId = TokenUtil.getOrgId(request.getHeader("token"));
            String opName = TokenUtil.getOpName(request.getHeader("token"));
            operatorLogService.insert("操作日志导出", "操作日志导出", "1", opId, opName, orgId);
            OperateHistoryBO operateHistoryBO = historyBOPaginationBO.getParams();
            if (StringUtils.isNotBlank(operateHistoryBO.getStartDateTime())) {
                operateHistoryBO.setStartDateTime(DateUtil.DateToStr(DateUtil.YYYYMMDDHHMMSS,DateUtil.getDate(DateUtil.YYYYMMDD_HHMMSS,operateHistoryBO.getStartDateTime() + " 00:00:00")));
            }
            if (StringUtils.isNotBlank(operateHistoryBO.getEndDateTime())) {
                operateHistoryBO.setEndDateTime(DateUtil.DateToStr(DateUtil.YYYYMMDDHHMMSS,DateUtil.getDate(DateUtil.YYYYMMDD_HHMMSS,operateHistoryBO.getEndDateTime() + " 23:59:59")));
            }
            //获取当前机构及下属机构id集合
            List<String> orgIds = getListOrgIds(operateHistoryBO.getOrgId());
            orgIds.add(operateHistoryBO.getOrgId());
            operateHistoryBO.setOrgIds(orgIds);
            // 执行查询
            List<OperateHistoryDTO> operateHistoryDTOS = operateHistoryMapper.getHistoryLog(operateHistoryBO);
            if (operateHistoryDTOS == null || operateHistoryDTOS.isEmpty()) {
                throw new RuntimeException("无数据无需导出");
            }
            String title = "操作日志导出" + Math.random() + ".xls";
            String[] headers = new String[]{"操作时间", "任务编号", "任务类型", "锁名称", "钥匙名称", "操作类型", "所属机构", "操作状态", "接收人1", "接收人2"};

            List<Object[]> dataList;
            dataList = operateHistoryDTOS.stream().map(operateHistoryDTO -> {
                Object[] obj = new Object[headers.length];
                obj[0] = operateHistoryDTO.getOperateTime();
                obj[1] = operateHistoryDTO.getMissionId();
                obj[2] = operateHistoryDTO.getMissionType();
                obj[3] = operateHistoryDTO.getLockName();
                obj[4] = operateHistoryDTO.getKeyName();
                obj[5] = operateHistoryDTO.getOperateType();
                obj[6] = operateHistoryDTO.getOrgName();
                obj[7] = operateHistoryDTO.getOperateStatus();
                obj[8] = operateHistoryDTO.getOpName1();
                obj[9] = operateHistoryDTO.getOpName2();
                return obj;
            }).collect(toList());

            OutputStream out = null;
            // 防止中文乱码
            String headStr = "attachment; filename=\"" + new String(title.getBytes("gb2312"), "ISO8859-1") + "\"";
            response.setContentType("octets/stream");
            response.setContentType("APPLICATION/OCTET-STREAM");
            response.setHeader("Content-Disposition", headStr);
            out = response.getOutputStream();
            ExcelOutput ex = new ExcelOutput(title, headers, dataList);
            ex.export(out);
            log.info("操作日志导出");

        } catch (Exception e) {
            log.error(ErrMessageConst.SYSTEM_ERROR, e);
            HeaderResult.setFailHeader(request, response, e.getMessage());
        }
    }

    public List<String> getListOrgIds(String orgId) {
        String strkey = "orgid:" + orgId;
        List<String> lists = null;
        lists = redisUtils.get(strkey, List.class);
        if (lists == null) {
            lists = new ArrayList<>();
            recursiveGetOrgId(lists, orgId);
        }

        return lists;
    }

    //递归查询子机构
    private void recursiveGetOrgId(List<String> lists, String orgId) {
        List<String> orgIdList = organizationMapper.getOrgIdsList(orgId);
        while (orgIdList.size() == 0) {
            return;
        }
        orgIdList.forEach(childOrgId -> {
            lists.add(childOrgId);
            recursiveGetOrgId(lists, childOrgId);
        });
    }


   /**
    * @author wp
    * @Description: 上传系统日志
    * @date 2022/10/8
    */
    @PostMapping(value = "/uploadSysLog")
    @ResponseBody
    @ApiOperation("上传系统日志")
    public BaseResult uploadSysLog(@Validated @RequestBody LogBO bo) {
        try {
            return operatorLogService.uploadSysLog(bo);
        } catch (Exception e) {
            log.error(ErrMessageConst.SYSTEM_ERROR, e);
            return GetResult.getResultErr();
        }
    }

}
